In [2]:
%pylab
from __future__ import print_function


Using matplotlib backend: TkAgg
Populating the interactive namespace from numpy and matplotlib

In [2]:

Carbon Fiber Mechanical Properties

  • E = 70 GPa (Young's modulus)
  • $\sigma_{ult}$ = 1.6 GPa (ultimate strength)
  • density = 1550 kg/$m^3$

Failure Modes

Bending

$$ \sigma = \frac{My}{I} $$

where

  • $\sigma$ = strain,
  • M = moment,
  • y = distance from neutral axis,
  • I = area moment of inertia.

Buckling

$$ F = \frac{\pi^2 E I}{KL^2} $$

where

  • F = maximum or critical force (vertical load on column),
  • E = modulus of elasticity,
  • I = area moment of inertia,
  • L = unsupported length of column,
  • K = column effective length factor, whose value depends on the conditions of end support of the column, as follows.
    • For both ends pinned (hinged, free to rotate), K = 1.0.
    • For both ends fixed, K = 0.50.
    • For one end fixed and the other end pinned, K = 0.699....
    • For one end fixed and the other end free to move laterally, K = 2.0.
  • KL is the effective length of the column.

Design Problem

Find the design with the most excess power given the motors.

Assuumptions

  • Rods running length of vehicle

Power Required

The absolute minimum power for flapping flight is given by:

$$ P_{mp} = \frac{1.05 k^{3/4} m^{3/2} g^{3/2} S_b^{1/4} C_{Db}^{1/4}}{\rho^{1/2}B^{3/2}} $$$$ V_{mp} = \frac{0.807 k^{1/4}m^{1/2}g^{1/2}}{\rho^{1/2}B^{1/2}S_b^{1/4}C_{Db}^{1/4}}$$$$f = m^{3/8}g^{1/2}B^{-23/24}S^{-1/3}\rho^{-3/8}$$

where

  • B : wing span
  • $C_{Db}$ : body drag coefficient
  • g : Acceleration due to gravity
  • k : Induced power factor
  • m : All-up mass
  • S_b : body frontal area

Power (Min Power)


In [3]:
# vehicle
B = 1.2 # wing span, m
C_Db = 0.1 # body drag coeff, m
k = 1.1 # induced power factor
m = 0.3 # mass
S_b = 0.003 # body frontal area
S = B/6

cf_E = 70e6
cf_ult_stress = 1.6e6
cf_dens = 1500

# environment
g = 9.8
rho = 1.225


P_mp = 1.05*k**(0.75)*m**(1.5)*g**(1.5)*\
    S_b**(0.25)*C_Db**(0.25)*rho**(-0.25)*B**(-1.5)
V_mp = 0.807*k**0.25*m**0.5*g**0.5*\
    rho**-0.5*B**-0.5*S_b**-0.25*C_Db**-0.25
f_mp = m**(3.0/8)*g**0.5*B**(-23.0/24)*S**(-1.0/3)*rho**(-3.0/8)
P_mp, V_mp
print("""P_mp: {P_mp:f} Watts
V_mp: {V_mp:f} m/s
f_mp: {f_mp:f} Hz""".format(**locals()))


P_mp: 0.541040 Watts
V_mp: 8.880888 m/s
f_mp: 2.652103 Hz

Power (Max Range)


In [4]:
S_d = pi*B**2/4
A = S_b*C_Db
V_mr = k**0.25*m**0.5*g**0.5*rho**-0.5*A**-0.25*S_d**-0.25
P_mr = k**0.75*m**1.5*g**1.5*A**0.25*rho**-0.25*S_d**-0.75
V_mr, P_mr


Out[4]:
(11.689888938416754, 0.6176216636797301)

Power Available

$$ P_{servo} = T \omega$$

where

  • $P_{servo}$ : available servo power
  • T : servo torque
  • $\omega$ : angular velocity of servo

Manufacturer Servo/Battery Data


In [53]:
ozIn2Nm = 0.00706155183333
T_servo = 300*ozIn2Nm # oz-in
omega_servo = deg2rad(60/0.06) # rad/s
eff_servo = 0.001 # total efficiency, setting to match Robo Raven performance
V_servo = 7.4 # volts
C_bat = 0.370 # battery capacity Ah
d_bat = 20 # battery discharge rating

Computed Servo/Battery Data


In [86]:
P_servos = 2*T_servo*omega_servo # watts, note 2 servos
A_servos = P_servos/ V_servo
flight_time = C_bat/A_servos*60 # minutes
A_bat = d_bat*C_bat

flight_time_mp = 4.75
A_mp = C_bat/flight_time_mp*60
eff_servo = P_mp/V_servo/A_mp

P_mp_eff = P_mp/eff_servo

print("""

min power
===========
flight time\t:{flight_time_mp:10.3f} min
P\t\t:{P_mp_eff:10.3f} Watts
A\t\t:{A_mp:10.3f} A

full power
===========
flight time\t:{flight_time:10.3f} min
P\t\t:{P_servos:10.3f} Watts
A\t\t:{A_servos:10.3f} A

battery
===========
A bat\t\t:{A_bat:10.3f} A
"""\
.format(**locals()))



min power
===========
flight time	:     4.750 min
P		:    34.585 Watts
A		:     4.674 A

full power
===========
flight time	:     2.222 min
P		:    73.948 Watts
A		:     9.993 A

battery
===========
A bat		:     7.400 A

We see that the battery is capable of supply the required discharge rate ($A_{bat} > A_{min\_power}$).

Calculated efficiency, so endurance mataches RoboRaven.


In [27]:
eff_servo*P_servos - P_mr


Out[27]:
1.0092430895726943

Maximize

Excess Power

Design Vector

  • B - wing span
  • S - wing area
  • l - length from nose to start of tail
  • a_t - angle of tail
  • l_t - length of tail
  • w_t - width of tail
  • d_f - diameter of fuselage rod
  • t_f - thickness of fuselage rod
  • d_w - diameter of wing rod
  • t_w - thickness of wing rod
  • n_f - number of fuselage rods
  • r_f - radius of fuselage rods

Constraints

  • Payload can be moved to set c.g. location to desired.
  • Longitudinally stable.
  • Laterally stable.
  • Wing rod can't bend more than 5 degrees.
  • Wing rod can't twist more than 5 degrees.
  • Fuselage can't bend more than 5 degrees.
  • Fuselage can't twist more than 5 degrees.
  • Wing rod survives crash on wing tip.
  • Fuselage survives crash on end.
  • Fuselage survives crash on side.

In [91]:
import scipy.optimize

def neg_excess_power(x):
    # design vector
    B = x[0] # wing span
    r_f = x[1] # diameter of fuselage rod
    t_f = x[2]
    
    # guess at structure relationship for now
    m = 4*pi*r_f*t_f*cf_dens
    S_b = B**2
    
    A = S_b*C_Db
    P_mp = 1.05*k**(0.75)*m**(1.5)*g**(1.5)*\
        S_b**(0.25)*C_Db**(0.25)*rho**(-0.25)*B**(-1.5)
    return -(P_servos - P_mp)

def stress_bend(x):
    # design vector
    B = x[0] # wing span
    r_f = x[1] # radius of fuselage rod
    t_f = x[2]
    
    M = B**2/6 # moment scales by square of length
    y = r_f
    I = pi*r_f**3*t_f
    return M*y/I
    
def stress_buckle(x):
    # design vector
    B = x[0] # wing span
    r_f = x[1] # radius of fuselage rod
    t_f = x[2]
    
    I = pi*r_f**3*t_f
    K = 2 # buckling with one end free
    F = pi**2*cf_E*I/(K*B**2)
    A = 2*pi*r_f*t_f
    return F/A
    
def con_bending(x):    
    return -(cf_ult_stress - stress_bend(x))
    
def con_buckling(x):    
    return -(stress_buckle(x) - stress_bend(x))

def callback(x):
    print(x)

x0 = [1, 1, 1]

constraints= [
    #{'type':'ineq', 'fun':con_bending},
    #{'type':'ineq', 'fun':con_buckling},
]

options = {'disp':True, 'iprint':2}
bounds = [(0.1,10), (0.1,10), (0.1,10)]
#bounds = None
method = 'slsqp'
res = scipy.optimize.minimize(neg_excess_power, x0, method=method, bounds=bounds,
                              constraints=constraints, options = options, callback=callback)
res


  NIT    FC           OBJFUN            GNORM
[ 1.  1.  1.]
    1     5     4.786190E+07     1.122463E+08
Inequality constraints incompatible    (Exit mode 4)
            Current function value: 47861898.1125
            Iterations: 1
            Function evaluations: 5
            Gradient evaluations: 1
Out[91]:
  status: 4
 success: False
    njev: 1
    nfev: 5
     fun: 47861898.112543397
       x: array([ 1.,  1.,  1.])
 message: 'Inequality constraints incompatible'
     jac: array([-47861971.,  71792958.,  71792958.,         0.])
     nit: 1